import { scheduleUpdateOnFiber } from "../reconciler/fiberWorkLoop";
import { IFiber } from "../reconciler/updateContainer";

interface IHook {
  memoizedState: any;
  next: IHook | null;
}

// 当前正在处理的 fiber
let currentlyRenderingFiber: IFiber | null = null;

// 正在处理的 hook
let workInProgressHook: any = null;

// 处理完的 hook
let currentHook: IHook | null = null;

export function renderWithHooks(wip: IFiber) {
  // 进行初始化操作
  currentlyRenderingFiber = wip;
  workInProgressHook = null;
  currentHook = null;

  // 存储副作用操作
  currentlyRenderingFiber.updateQueue = [];
}

function updateWorkInProgressHook() {
  let hook: IHook | null = null;

  // 判断是否为第一次渲染
  const currentFiber = currentlyRenderingFiber?.alternate;
  if (!currentFiber) {
    // 是第一次渲染
    hook = {
      memoizedState: null,
      next: null,
    };

    // 是否有链表，有则指向下一个hook
    if (workInProgressHook) {
      // 有链表
      workInProgressHook = workInProgressHook.next = hook;
    } else {
      // 没有链表
      workInProgressHook = currentlyRenderingFiber!.memorizedState = hook;
    }
  } else {
    // 不是第一次渲染
    // 复用hook
    currentlyRenderingFiber!.memorizedState = currentFiber.memorizedState;

    // 是否存在链表
    if (workInProgressHook) {
      // 存在
      workInProgressHook = hook = workInProgressHook.next;
      currentHook = currentHook!.next;
    } else {
      // 不存在
      // 不是第一次渲染证明fiber上保存着hook链表
      workInProgressHook = hook = currentlyRenderingFiber!.memorizedState;

      currentHook = currentFiber.memorizedState;
    }
  }

  return hook as IHook;
}

function dispatchReducerAction(fiber: IFiber, hook: IHook, reducer: ((value: any) => any) | null, action: any) {
  // 这里的reducer有可能会出现没有值的情况，没有值则证明使用的时 useState

  // 计算出新值，若没有reducer则action就是最新的值
  hook.memoizedState = reducer ? reducer(hook.memoizedState) : action;

  // 更新状态之后该fiber就是一个旧fiber了，这里需要做一个指向操作
  fiber.alternate = { ...fiber };

  // 断开兄弟节点的链接，不去更新兄弟节点
  fiber.sibling = null;

  scheduleUpdateOnFiber(fiber);
}

export function useState(initialState: any) {
  return useReducer(null, initialState);
}

export function useReducer(reducer: ((value: any) => any) | null, initialState: any) {
  const hook: IHook = updateWorkInProgressHook();

  // 首次渲染时对hook的值进行初始化
  if (!currentlyRenderingFiber?.alternate) {
    hook.memoizedState = initialState;
  }

  const dispatch = dispatchReducerAction.bind(null, currentlyRenderingFiber as IFiber, hook, reducer);

  return [hook.memoizedState, dispatch];
}
